#ifndef XGE_GRAPHICS_STUFF_H_
#define XGE_GRAPHICS_STUFF_H_
#include "xge_common_config.h"

#include "xtimer.h"
#include "xtype.h"
#include "g_texture.h"
#include "xsmart_ptr.h"
#include "xdata_structure.h"

namespace xge{
namespace graphics{

  class RenderTargetNode;
  using xge::xge_internal::Timer;
  class SceneManager;
  class Graphics2D;

  // Stuff ! This is only a joke name . I just put many
  // uncategorized stuff here to make our later render layer
  // easy to implement .

  // In most game engine implementation , everything starts
  // from a root node : like Orge SceneNode , Irrlicht SceneNode.
  // This is typically very good for the user , since the 
  // same interface will hide the detail implementation of
  // organization of certain kind of node. Like some scene node
  // can be wrapped into the OCTree manager , and the user
  // do not need to know this . However , in our engine , we
  // will take advantage of multi-thread ,so , the original
  // design seems to be of much difficulty to implement , for
  // performance reason , some node will be refreshed inside 
  // the main loop , some will refreshed inside of other loop .
  // In fact , every node will receive message through different
  // ways , so we do not make all this thing rigid .

  // We divide the node into different category 
  // Since the rendering will always be used in the main loop 
  // however the logical thread will possible be concurrent from
  // the current main loop .

  // Rendering Node 
  // This rendering node will always be called inside of the main
  // loop !

  class BaseNode : public xge_internal::IntrinsicPointer<BaseNode> {
  public:
    // the on paint will receive the different time between 
    // last call to this OnPaint function as well as the 
    // frame difference appending , in expected mode , the
    // diff_frame may keep stable as 1.
    virtual void OnPaint ( const Timer::tick_t& diff_time  )  = 0 ;
  protected:
    // This rendering node parameter will created a no parent node which
    // using the default constructor to construct this node 
    BaseNode();
    // This constructor will use the following parameter to construct a node
    // which do not have parent node 
    BaseNode( const TexturePtr& texture , const Rect&  texture_rect ,
      const Point& anchor , const Point& scale , const Point& position, float rotation );
  public:
    // This constructor will create the node 
    virtual ~BaseNode() = 0;
  public:
    // SetPosition will set the position 
    // to the screen coordinate
    inline void set_position( const Point& pos ) {
      position_ = pos;
    }
    const Point& position() const {
      return position_;
    }
    // This function should be virtual 
    // since the detail implementation changes
    virtual void set_texture( const TexturePtr& texture ) {
      // since the adjust texture coordinate
      // will consume lots times , we do 
      // a test to avoid it
      if( texture.Get() == texture_.Get() ) 
        return;
      // do the copy 
      texture_ = texture;
    }
    const TexturePtr& texture() const {
      return texture_;
    }
    // Setting the texture rect
    // This function should be virtual , since
    // many implementation can change the internal
    // mechanism !
    virtual void set_texture_rect( const Rect& rect ) {
      texture_rect_ = rect;
    }
    const Rect& texture_rect() const {
      return texture_rect_;
    }
    // Scale setting
    void set_scale ( const Point& scale ) {
      scale_ = scale;
    }
    const Point& scale() const {
      return scale_;
    }
    // Set the anchor point
    void set_anchor( const Point& pt ) {
      anchor_ = pt ;
    }
    Point anchor() const {
      return anchor_;
    }
    // Set the current rotation 
    void set_rotation( float rot ) {
      rotation_ = rot;
    }
    float rotation() const {
      return rotation_;
    }
  public:
    // the following function has its default implementation
    // if the target node do not have this feature , just
    // leave this function as not implemented .
    virtual void set_z( float z ){}
    virtual float z() const { return -1.0f; }
    virtual void set_color( const Color& color , size_t index ) {}
    virtual Color color( size_t index ) { return Color(); }
    virtual void set_blending( int blending ){}
    virtual int blending() const { return DUMMY_BLEND_VALUE; }

  public:
    // The child node management function will be implemented as the 3D game engine!
    // Make it all virtual function , since we do not know the specific data-structure
    // to manage the child node , it may be OCTree or just list , anyway  , you can 
    // implemented as you wish !

    // This will add a child node into this node child 
    // list 
    virtual void AddChildNode( BaseNode* node ) = 0;
    // This will remove a child node inside of this node list
    // You should always remove the node which has been
    // existed in this child list , otherwise the operation is
    // undefined !
    virtual void RemoveChildNode( BaseNode* node ) = 0;
    // Size of the child list
    virtual size_t NumberOfChild() const  = 0 ;
    // If the size is empty or not
    virtual bool IsChildListEmpty() const  = 0 ;
    // Clear the child node
    virtual void ClearChildList() = 0;
    // Get the parent node of this rendering node !
    BaseNode* parent() const {
      return parent_;
    }
  public:
    // This function will return an internal tag for the node
    // type 
    virtual int GetNodeType() const = 0;
  protected:
    // The following function is used for the derived class 
    static Graphics2D* GetGraphics2D() ;
    // The following function is to provide additional workaround of
    // nested calling of BeginScene and EndScene so , calling the following
    // function will help you to deal with nested calling of the function

    // The BeginScene function here can be nested , in fact , it internally
    // do such thing: 
    // 1. Push the last rendering state into the state stack ,finish the batch !
    // 2. Push the current rendering state into the state stack , and invoking the 
    // Graphics2D::BeginScene internally 
    // Return value is the stack depth of this begin scene calling !
    // If this function calling is failed , you can check the state of the RootNode 
    // by calling the error function 
    static int BeginScene ( int rendering_mode , int primitive_type ,
    RenderTargetNode* render_target_node , const TexturePtr& texture_ptr ,
    int blending_mode , size_t wait_time_out = 100 );

    // The EndScene function here can be nested , in fact , it internally do such
    // thing:
    // 1. Finish the last rendering state by calling Graphics2D::EndScene internally 
    // 2. Resume the BeginScene state back by using the state stack 
    // 3. Pop the rendering state stack !
    // Return value is the stack depth of this end scene calling !
    // If this function calling is failed , you can check the state of the RootNode 
    // by calling the error function 
    static int EndScene ();
    // Get the calling of BeginScene and EndScene nested depth !
    static size_t CallingStackDepth() {
      return kStackDepth;
    }
  protected:
    // for the derived class using 
    void set_parent( BaseNode* node ) {
      // Its parent can be null which means it is
      // not added in any node !
      if( parent_ )
        parent_->Drop();
      // Its target parent can be any node which means
      // it is not in any node as well 
      if( node )
        node->Grab();
      // attach the parent 
      parent_ = node;
    }
  private:
    // The rendering parameter stuff goes here
    Point position_, anchor_ , scale_;
    Rect texture_rect_ ;
    TexturePtr texture_;
    float rotation_;
    // The friend class 
    friend class SceneManager;
    // The rendering node parent
    BaseNode* parent_;
  private:
    // The internal state structure 
    struct G2DRenderState {
      int mode , ptype ;
      RenderTargetNode* rt_node;
      TexturePtr texture_ptr;
      int blending_mode ;
      size_t w_timeout;
      G2DRenderState( int m , int pt , RenderTargetNode* rt_n , 
        const TexturePtr& t_ptr , int bm , int wtm );
      ~G2DRenderState();
    };
    typedef xge::stack< G2DRenderState >::Stack G2DRenderStateStack;
    static G2DRenderStateStack kG2DStateStack;
    // since the stl::stack do not provide depth function
    // we keep a depth tag by ourself 
    static size_t kStackDepth;
  };

  // This ListBaseNode class will using the common list data structure to manage
  // the internal data of child node , in 2D game , this organization is enough !

  class ListBaseNode : public BaseNode {
  public:
    enum {
      NODE_TYPE_LIST_BASE_NODE = 1
    };
    virtual void AddChildNode( BaseNode* node );
    virtual void RemoveChildNode( BaseNode* node ) {
      if( node->GetNodeType() != GetNodeType() )
        return;
      RemoveChildNodeInternal(node);
    }
    virtual size_t NumberOfChild() const {
      return child_list_.size();
    } 
    virtual bool IsChildListEmpty() const {
      return child_list_.empty();
    }
    virtual void ClearChildList();

    // This OnPaint function will commonly calling every
    // child node in the list (their OnPaint function )
    virtual void OnPaint( const Timer::tick_t& diff_time );
  public:
    virtual int GetNodeType() const {
      return NODE_TYPE_LIST_BASE_NODE;
    }

    ListBaseNode();
    ListBaseNode(const TexturePtr& texture , const Rect&  texture_rect ,
      const Point& anchor , const Point& scale , const Point& position, float rotation );

    virtual ~ListBaseNode() {
      ClearChildList();
    }
  private:
    // Simply using the std::list as our default datastructure for holding
    // the node internally !
    typedef xge::list< ListBaseNode* >::List RenderingNodeList;
    typedef RenderingNodeList::iterator NodeIdentity;

    NodeIdentity RemoveChildNodeInternal ( BaseNode* node );

#ifdef _DEBUG
    // In debug version , we will use this function to check weather a
    // node is in this child node list ,which is used to avoid the undefined
    // behavior of the node
    bool IsThisNodeExistInChildList( BaseNode* node );
#endif
  private:
    RenderingNodeList child_list_;
    friend class SceneManager;
    // Using this tag to accelerate the the remove operation !
    NodeIdentity  id_;
  };



}// namespace graphics
}// namespace xge

#endif// XGE_GRAPHICS_STUFF_H_